package com.sakura.probe.controller;


import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.code.kaptcha.Constants;
import com.sakura.probe.common.api.CommonResult;
import com.sakura.probe.common.util.JwtTokenUtil;
import com.sakura.probe.common.util.SMSUtil;
import com.sakura.probe.nosql.redis.RedisKey;
import com.sakura.probe.nosql.redis.RedisService;
import com.sakura.probe.pojo.PersonInfo;
import com.sakura.probe.pojo.Topic;
import com.sakura.probe.pojo.TopicCategory;
import com.sakura.probe.service.HeadLineService;
import com.sakura.probe.service.PersonInfoService;
import com.sakura.probe.service.TopicCategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;


/**
 * @author Sakura
 */
@Api(tags = "LoginController",description = "用户登录注册等相关操作")
@Controller
@RequestMapping("/person")
public class LoginController {
    @Autowired
    private PersonInfoService personService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private HeadLineService headLineService;
    @Autowired
    private TopicCategoryService topicCategoryService;


    @ApiOperation("用户登录")
    @PostMapping("/login")
    @ResponseBody
    public CommonResult login(String username, String password){
        PersonInfo person = personService.getOne(new QueryWrapper<PersonInfo>().eq("phone", username)
                .or().eq("mail", username));
        if (null==person){
            return CommonResult.failed("账号错误");
        }else if (!(person.getPassword()).equals(SecureUtil.md5(password))){
            return CommonResult.failed("密码错误");
        }
        //将用户信息存储在redis中并设置存活时间为12h
        redisService.set(RedisKey.getPersonInfo()+person.getUserId(),JSONUtil.toJsonStr(person),60*60*12);
        //登录成功后返回生成的token给前台页面
        return CommonResult.success(person.getUserId(),JwtTokenUtil.createToken(String.valueOf(person.getUserId())));
    }

    @ApiOperation("用户注册")
    @PostMapping("/register")
    @ResponseBody
    public CommonResult register(String phone,String code,String password){
        //先判断手机验证码是否正确
        String realCode = redisService.get(RedisKey.getPhoneCode()+phone);
        if (null == realCode || !realCode.equals(code)){
            return CommonResult.failed("验证码错误或未发送验证码到指定手机中");
        }
        PersonInfo person = new PersonInfo("Pb:"+RandomUtil.randomNumbers(10),
                SecureUtil.md5(password),phone);
        boolean result = personService.save(person);
        return result?CommonResult.success("注册成功"):CommonResult.failed("注册失败");
    }

    @ApiOperation("通过手机号找回密码")
    @ResponseBody
    @PostMapping("/retrieve")
    public CommonResult retrieve(HttpServletRequest request, String phone,String password,
                                 String phoneCode, String code){
        //先判断验证码是否正确
        String verifyCodeExpected = (String) request.getSession()
                .getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if ( verifyCodeExpected==null || !code.equals(verifyCodeExpected)){
            return CommonResult.failed("验证码错误");
        }
        //接着判断该手机是否有注册过
        PersonInfo person = personService.getOne(new QueryWrapper<PersonInfo>().eq("phone", phone));
        if (null == person){
            return CommonResult.failed("该手机号未注册过");
        }
        //然后判断手机验证码是否输入正确
        String realCode = redisService.get(RedisKey.getPhoneCode()+phone);
        if (null==realCode||!phoneCode.equals(realCode)){
            return CommonResult.failed("手机验证码输入错误或验证码发送错误");
        }
        person.setPassword(SecureUtil.md5(password));
        boolean result = personService.updateById(person);
        return result?CommonResult.success("修改成功"):CommonResult.failed("修改失败");
    }

    @ApiOperation("发送手机验证码")
    @ResponseBody
    @GetMapping("/sendPhoneCode")
    public CommonResult sendPhoneCode(String phone,String type){
        //先判断该手机是否有注册过
        PersonInfo person = personService.getOne(new QueryWrapper<PersonInfo>().eq("phone", phone));
        if ("retrieve".equals(type)&&null==person){
            //用于修改密码时发送验证码,那么只需判断该手机号是否没有注册过
            return CommonResult.failed("该手机号未注册过");
        }else if ("register".equals(type)&&null!=person){
            //用于注册账号时发送验证码,那么只需判断该手机号是否有注册
            return CommonResult.failed("该手机号已注册过");
        }
        //生成随机4位的验证码,并发送到对应手机中
        String code = RandomUtil.randomNumbers(4);
        boolean result = SMSUtil.sendcode(phone, code);
        if (result){
            //发送成功则将验证码存入redis中并设置存活时间为5分钟=300秒
            redisService.set(RedisKey.getPhoneCode()+phone,code,300);
        }
        return result?CommonResult.success("发送成功"):CommonResult.failed("发送失败");
    }

    @ApiOperation("登录成功后跳转的页面——获取首页相关的信息")
    @ResponseBody
    @GetMapping("/index")
    public Map<String,Object> index(){
        Map<String,Object> modelMap = new HashedMap();
        //获取一级话题类别列表(即parentId为空的类别)
        List<TopicCategory> topicCategoryList = topicCategoryService.getTopicCategoryList();
        //获取状态为可用(1)的头条列表
        List<Topic> headLineList = headLineService.getHeadLineList();
        modelMap.put("topicCategoryList",topicCategoryList);
        modelMap.put("headLineList",headLineList);
        modelMap.put("success",true);
        return modelMap;
    }

    @ApiOperation("从token中获取用户的基本信息")
    @ResponseBody
    @GetMapping("/getPerson")
    public CommonResult<PersonInfo> getPersonInfo(String token){
        PersonInfo person = redisService.getPersonByToken(token);
        return null==person?CommonResult.failed():CommonResult.success(person);
    }


    @ApiOperation("退出该账号,将登陆的用户信息从redis中删除")
    @ResponseBody
    @GetMapping("/logout")
    public CommonResult logout(String token){
        try {
            redisService.remove(RedisKey.getPersonInfo()+JwtTokenUtil.getUsernameFromToken(token));
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success(null);
    }

}
